package org.halk.demo;

import org.junit.Test;

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * ##### 1、ThreadPoolExecutor参数有哪些
 * - corePoolSize
 * - 核心线程数
 * - maximumPoolSize
 * - 线程池中的最大线程数
 * - keepAliveTime
 * - 线程池中超过核心线程数的线程最大等待时间
 * - unit
 * - keepAliveTime 对应的时间单位，为TimeUnit类
 * - workQueue
 * - 阻塞队列，当线程池中线程数超过corePoolSize时，用于存储提交的任务
 * - threadFactory
 * - 线程池用来创建线程的线程工厂
 * - handler
 * -  当线程线中线程已满不在执行任务时，执行的策略
 * ##### 2、一个任务提交线程池后，线程池创建线程执行任务的流程
 * -  1、提交任务时 线程池中用来执行任务的线程数 < corePoolSize（核心线程数）, 则用threadFactory(线程工厂)创建线程用于执行提交的任务
 * - 2、大于核心线程数，且workQueue未满，则放入队列，等待其他线程执行任务后循环从队列中取
 * - 3、大于核心线程数，且workQueue已满，且没有超过最大线程数，则使用线程工厂创建新的线程执行
 * - 4、大于最大线程数，且队列已满，则执行配置的拒绝策略
 * <p>
 * **注意**
 * - 不建议采用很大的ArrayBlockQueue或不限大小的LinkedBlockQueue
 * - CUP密集的任务corePoolSize也不应该设置过大
 * - IO密集的任务则corePoolSize则可以设置的大一点，可以避免长时间IO等待而CUP却空闲
 * - threadFactory建议采用自己定义的，让其创建的线程容易区分，方便问题定位。
 *
 * @Author halk
 * @Date 2023/7/14 14:31
 */
public class ThreadPoolExecutorDemo {

    @Test
    public void test01() throws InterruptedException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                3,
                5,
                1,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(4),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        //超过等待时间后允许核心线程数销毁
        threadPoolExecutor.allowsCoreThreadTimeOut();

        System.out.println("开始执行任务---" + new Date());

        for (int i = 0; i < 10; i++) {
            int finalI = i;
            threadPoolExecutor.execute(() -> {
                System.out.println(Thread.currentThread().getName() + " 休眠中 " + finalI);
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            });
        }
        Thread.sleep(5000);
        System.out.println("当前执行任务的线程数： " + threadPoolExecutor.getActiveCount());
        System.out.println("核心线程数：  " +threadPoolExecutor.getPoolSize());


        System.out.println("任务结束---"  + new Date());
        Thread.sleep(1000000);
    }
}
